package com.xiaotu.spider.sohu.pageprocessor;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.selector.Html;

import com.xiaotu.common.exception.SpiderException;
import com.xiaotu.common.exception.SpiderExceptionCode;
import com.xiaotu.common.model.TVPubCommentModel;
import com.xiaotu.common.model.TVRecordModel;
import com.xiaotu.common.model.TVSetsPlotModel;
import com.xiaotu.common.util.Constants;
import com.xiaotu.common.util.HttpUtils;
import com.xiaotu.common.util.KeywordEncode;
import com.xiaotu.common.util.PageUtils;
import com.xiaotu.common.util.RegexUtils;
import com.xiaotu.common.util.StringUtil;
import com.xiaotu.common.util.TVProcessUtils;
import com.xiaotu.spider.APageProcessor;

/**
 * 爬取电视剧相关信息类
 */
@Component("SohuPageProcessor")
@Scope("prototype")
public class SohuPageProcessor extends APageProcessor
{
	
	@Override
	protected Request getStartRequest(JSONObject target)
	{
		return new Request("http://so.tv.sohu.com/mts?box=1&wd="
				+ KeywordEncode.encode(target.getString("tvName")));
	}
	
	@Override
	public void process(Page page)
	{
		Map<String, Object> tvMap = page.getRequest().getExtras();
		switch (this.getPageDataType(page))
		{
			case Constants.PageDataType.SEARCH_LIST:
				this.searchListProcess(page, tvMap);
				break;
			case Constants.PageDataType.TV_RECORD:
				this.tvRecordProcess(page, tvMap);
				break;
			case Constants.PageDataType.TV_COMMENT:
				this.commentProcess(page, tvMap);
				break;
			case Constants.PageDataType.TV_PLOTSET:
				this.setProcess(page, tvMap);
				break;
			default:
				break;
		}
	}
	
	private void searchListProcess(Page page, final Map<String, Object> tvMap)
	{
		Html html = page.getHtml();
		final List<String> divList = html.xpath("//div[@class='ssItem cfix']")
				.all();
		
		String firstTime = html
				.xpath("//div[@class='ssItem cfix']/div[@class='center']"
						+ "/div[1]/span[@class='ndai']/text()").toString();
		firstTime = RegexUtils.regexSearch(RegexUtils.REGEX_INTEGER, firstTime);
		tvMap.put("firstTime", firstTime);

		// 链接标签
		final List<String> aList = html
				.xpath("//div[@class='ssItem cfix']/div[@class='center']/div[1]/div[@class='infoA cfix lan_infoA']/h2/a")
				.all();
		if (aList.size() == 0)
			aList.addAll(html
					.xpath("//div[@class='ssItem cfix']/div[@class='center']/div[@class='infoA cfix lan_infoA']/h2/a")
					.all());
		
		if (null == aList || aList.size() == 0)
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		
		// 剧名称
		List<String> tvNames = html
				.xpath("//div[@class='ssItem cfix']/div[@class='center']/div[1]/div[@class='infoA cfix lan_infoA']/h2/a/font/text()")
				.all();
		if (tvNames.size() == 0)
			tvNames = html
					.xpath("//div[@class='ssItem cfix']/div[@class='center']/div[@class='infoA cfix lan_infoA']/h2/a/font/text()")
					.all();
		
		// 电视剧类型
		List<String> tvTypes = html
				.xpath("//div[@class='ssItem']/div[@class='center']/div[1]/div[@class='infoA cfix lan_infoA']/span[@class='label-red']/em/text()")
				.all();
		if (tvTypes.size() == 0)
			tvTypes = html
					.xpath("//div[@class='ssItem']/div[@class='center']/div[@class='infoA cfix lan_infoA']/span[@class='label-red']/em/text()")
					.all();
		
		List<String> actorsAndDirectorsUL = html
				.xpath("//div[@class='ssItem']/div[@class='center']/ul[@class='infoB cfix']")
				.all();
		
		List<List<String>> actorsAndDirectorsList = new ArrayList<List<String>>();
		
		for (int i = 0; i < actorsAndDirectorsUL.size(); i++)
		{
			Html actorsAndDirectorsHTML = new Html(actorsAndDirectorsUL.get(i));
			actorsAndDirectorsList
					.add(actorsAndDirectorsHTML.xpath("//a/text()").all());
		}
		
		// 作品div列表，从中获取年份和站点
		// final List<String> divList = html
		// .xpath("//div[@class='wrap cfix']//div[@class='ssItem cfix']")
		// .all();
		
		if (aList.size() != tvTypes.size()
		// || aList.size() != divList.size()
				|| aList.size() != actorsAndDirectorsList.size()
				|| aList.size() != divList.size())
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		
		TVProcessUtils.addTVFromSearchList(page, tvMap, tvNames, aList, tvTypes,
				actorsAndDirectorsList, actorsAndDirectorsList,
				new TVProcessUtils.TVMatcher()
				{
					@Override
					protected boolean addTV(Page page,
							Map<String, Object> tvinfoMap, String name,
							String tvType, List<String> actors,
							List<String> directors, String link, int idx)
					{
						if (TVProcessUtils.tvMatched(tvinfoMap, name,
								TVProcessUtils.getTVType(tvType), actors,
								directors)
								&& Constants.SiteName.SOHU
										.equals(new Html(divList.get(idx))
												.xpath("//div[@class='center']/div[@class='lan_resource']//ul/li[@class='on']/em/text()")
												.get() + "视频"))
						{
							/*String  yugaop = new Html(divList.get(idx)).xpath("//div[@class='left']//div[@class='pic lan_pic']//em").get();
							if(StringUtil.isEmpty(yugaop))
							System.out.println(yugaop);*/
							
							Html aHtml = new Html(link);
							String playId = aHtml.xpath("//a/@_s_a").get();
							
							// PageUtils.addTargetRequest(page,
							// "http://vote.biz.itc.cn/query/score.json?callback=jQuery1720025488134910655935_1489141918563&albumId="
							// + playId + "&_=1489141918675",
							// tvinfoMap);// 评分链接
							
							String scoreJson = HttpUtils.httpGetJSONP("http://vote.biz.itc.cn/query/score.json?"
									+ "callback=jQuery1720025488134910655935_1489141918563&albumId="+ playId + "&_=1489141918675");
							scoreJson = RegexUtils.regexSearch(
							 "\"score\":\"" + RegexUtils.REGEX_NUMBER + "\"", scoreJson);//获取评分
							if(StringUtil.isNotEmpty(scoreJson)){
								scoreJson =RegexUtils.regexSearch(RegexUtils.REGEX_NUMBER,scoreJson);
								tvinfoMap.put("score", scoreJson);
							}
							
							PageUtils.addTargetRequest(page,
									"http://count.vrs.sohu.com/count/query_Album.action?albumId="
											+ playId,
									tvinfoMap, true);// 播放量链接
							
							PageUtils.addTargetRequest(page,
									"http://pl.hd.sohu.com/videolist?playlistid="
											+ playId
											+ "&order=0&cnt=1&callback=__get_videolist",
									tvinfoMap);// 分集梗概链接
							PageUtils.addTargetRequest(page,
									"http://changyan.sohu.com/api/2/topic/load?client_id=cyqyBluaj&topic_url="
											+ aHtml.xpath("//a/@href").get()
											+ "&topic_source_id=vp" + playId
											+ "&page_size=30",
									tvMap);// 添加评论链接
							
							return true;
						}
						return false;
					}
				}, getGetter(divList));
	}
	
	/**
	 * 设置已更新集次
	 * @param tvInfoMap
	 * @param divObj
	 */
	private TVProcessUtils.UpdateSetGetter getGetter(final List<String> divList)
	{
		return new TVProcessUtils.UpdateSetGetter()
		{
			@Override
			public String getUpdateSet(int idx)
			{
				return new Html(divList.get(idx))
						.xpath("//div[@class='center']/div[@class='infoA cfix']/span[2]/text()")
						.regex("更新至" + RegexUtils.REGEX_INTEGER + "集")
						.regex(RegexUtils.REGEX_INTEGER).get();
			}
		};
	}
	
	private void tvRecordProcess(Page page, Map<String, Object> tvMap)
	{
		String json = page.getRawText();
		if (StringUtils.isEmpty(json))
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
			
		// scoreJson = RegexUtils.regexSearch(
		// "\"score\":\"" + RegexUtils.REGEX_NUMBER + "\"", scoreJson);//获取评分\
		
		json = RegexUtils.regexSearch("count=" + RegexUtils.REGEX_INTEGER,
				json);
		if (StringUtils.isEmpty(json))
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		
		page.putField(TVRecordModel.class.getName(), new TVRecordModel(
				tvMap.get("tvid") + "", TVProcessUtils.getPageTVName(tvMap),
				Constants.SiteName.SOHU, tvMap.get("score")+"",
				RegexUtils.regexSearch(RegexUtils.REGEX_NUMBER, json), null,
				null, null, null, TVProcessUtils.getPageUpdateSet(tvMap),tvMap.get("firstTime") + ""));
	}
	
	private void setProcess(Page page, Map<String, Object> tvMap)
	{
		
		String json = page.getRawText();
		if (StringUtils.isEmpty(json) || !json.contains("(")
				|| !json.contains(")"))
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		int start = json.indexOf("(");
		int end = json.lastIndexOf(")");
		if (start >= end)
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		JSONObject resObj = JSONObject
				.fromObject(json.substring(start + 1, end));
		if (resObj == null || resObj.isEmpty() || !resObj.has("videos"))
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		JSONArray setArray = resObj.getJSONArray("videos");
		if (setArray == null || setArray.size() < 1)
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		
		List<TVSetsPlotModel> setsList = new ArrayList<TVSetsPlotModel>();
		
		for (int i = 0; i < setArray.size(); i++)
		{
			JSONObject setObj = setArray.getJSONObject(i);
			if (setObj == null || setObj.isEmpty() || !setObj.has("order")
					|| !setObj.has("videoDesc"))
				continue;
			setsList.add(new TVSetsPlotModel(tvMap.get("tvid") + "",
					tvMap.get("tvName") + "", setObj.getString("order"),
					setObj.getString("videoDesc")));
		}
		
		if (setsList.isEmpty())
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		page.putField(TVSetsPlotModel.class.getName() + "List", setsList);
	}
	
	private void commentProcess(Page page, Map<String, Object> tvMap)
	{
		String jsonStr = page.getRawText();
		// format json
		jsonStr = jsonStr.substring(jsonStr.indexOf("{"));
		
		jsonStr = jsonStr.substring(0, jsonStr.lastIndexOf("}") + 1);
		
		JSONObject C_json = JSONObject.fromObject(jsonStr);
		
		if (!C_json.containsKey("comments"))
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		
		JSONArray comments = C_json.getJSONArray("comments");
		
		List<TVPubCommentModel> modelList = new ArrayList<TVPubCommentModel>();
		for (int i = 0; i < comments.size(); i++)
		{
			JSONObject comment = comments.getJSONObject(i);
			
			if (!comment.containsKey("content"))
				continue;
			
			if (!comment.containsKey("create_time")
					|| StringUtils.isEmpty(comment.getString("create_time")))
				continue;
			
			if (!comment.containsKey("passport"))
				continue;
			
			modelList.add(new TVPubCommentModel(tvMap.get("tvid") + "",
					tvMap.get("tvName") + "", Constants.SiteName.SOHU,
					comment.getJSONObject("passport").getString("nickname")
							.replace("'", "''"),
					comment.getString("content").replace("'", "''"),
					comment.getString("create_time"), null,
					page.getUrl().toString()));
		}
		if (modelList.isEmpty())
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		page.putField(TVPubCommentModel.class.getName(), modelList);
	}
	
	@Override
	protected String getSpiderType()
	{
		return Constants.SpiderTaskType.TV_SOHU;
	}
	
	@Override
	public String getPageDataType(Page page)
	{
		String url = page.getUrl().toString();
		if (url.contains("http://so.tv.sohu.com/mts?box=1&wd="))
			return Constants.PageDataType.SEARCH_LIST;
		else if (url.contains(
				"http://changyan.sohu.com/api/2/topic/load?client_id=cyqyBluaj&topic_url="))
			return Constants.PageDataType.TV_COMMENT;
		else if (url
				.contains("http://count.vrs.sohu.com/count/query_Album.action"))
			return Constants.PageDataType.TV_RECORD;
		else
			return Constants.PageDataType.TV_PLOTSET;
	}
	
}
